/*
 generator生成器函数
   创建：function* xxx(...){} 「只能基于普通函数创建」
   执行：let itor = xxx(...)
     + 函数并没有执行（或者函数体中的代码并没有执行）
     + 返回一个具备iterator迭代器规范的对象「itor.next/return/throw」
   特点：可以基于 itor.next 控制函数的执行，在配合 yield 可以让函数体中的代码一步步的执行！！
     + 每一次执行next方法，控制函数中的代码执行，直到遇到一个 yield 结束！
     + 执行next的返回值是一个对象
       + value:存储本次遇到的yield后面的内容{或者是函数最后的返回值}
       + done:代码是否已经执行完毕
 */

/* function fn() {
  return 10
}
console.log(fn()) //10 */

/* // 创建函数，并且加一个*，则函数为生成器函数
function* fn() {
  console.log('AAA')
  return 10
}
console.log(fn()) //看似把函数执行，但是函数并没有执行（最起码函数体中的代码并没有执行），返回结果是：一个具备迭代器规范的对象（迭代器对象），具备 next/throw/return 三个方法
// new fn() //Uncaught TypeError: fn is not a constructor 
// const fn = *() => { } //Uncaught SyntaxError: Unexpected token '*' (at => 生层器函数只能基于function创建 */



/* // 生成器函数执行的时候，函数体中的代码并没有执行，只有通过返回的迭代器对象，基于 next 方法执行的时候，函数体中的代码才会自上而下执行，而且遇到 yield/return 结束！
// yield/return 后面的值，就是返回对象中 value 属性的值
// 对象中的 done 属性是：遇到 yield 是false，遇到 return 是true
function* fn() {
  console.log('A')
  yield 10
  console.log('B')
  yield 20
  console.log('C')
  return 30
}
let itor = fn() 
console.log(itor.next()) //输出‘A’  返回 {value:10,done:false}
console.log(itor.next()) //输出‘B’  返回 {value:20,done:false}
console.log(itor.next()) //输出‘C’  返回 {value:30,done:true}
console.log(itor.next()) //返回 {value:undefined,done:true}
// 生成器函数的作用：可以基于 yield 和 迭代器规范，控制函数体中的代码一步步的去执行 */


/* function* fn() {
  console.log('A')
  yield 10
  console.log('B')
  yield 20
  console.log('C')
}
let itor = fn()
console.log(itor.next()) //输出‘A’  返回{value:10,done:false}
/!* console.log(itor.throw('哈哈哈')) //直接抛出异常错误，错误原因‘哈哈哈’，后续代码都不会再执行
console.log(itor.next()) //这行代码也不再执行 *!/
console.log(itor.return('哈哈哈')) //说明函数执行已经结束，函数体中的后续代码都不会执行，本次返回 {value:'哈哈哈',done:true}，但是不会影响其后面的代码执行
console.log(itor.next()) //返回 {value:undefined,done:true} */


/* function* fn1() {
  yield 10
  yield 20
}
function* fn2() {
  yield 30
  yield fn1()
  yield 40
}
let itor = fn2()
console.log(itor.next()) //{value:30 ,done:false }
console.log(itor.next()) //{value:fn1执行返回的迭代器对象 ,done:false }
console.log(itor.next()) //{value:40 ,done:false }
console.log(itor.next()) //{value:undefined ,done:true }
console.log(itor.next()) //{value:undefined ,done:true } */

/* function* fn1() {
  yield 10
  yield 20
}
function* fn2() {
  yield 30
  yield* fn1()  //yield* 可以控制进入另外一个生成器函数中去执行
  yield 40
}
let itor = fn2()
console.log(itor.next()) //{value:30 ,done:false }
console.log(itor.next()) //{value:10 ,done:false }
console.log(itor.next()) //{value:20 ,done:false }
console.log(itor.next()) //{value:40 ,done:false }
console.log(itor.next()) //{value:undefined ,done:true } */


/*
 yiled 后面的值：作为本次 next 执行，返回对象中的 value 的属性值
 next 函数传递的值：作为上一次 yield 执行的返回结果「或者说 yield 执行的返回结果，是下一次执行 next ，传递的实参信息」，所以第一次执行 next 传递的值是没有用的！
 */
/* function* fn(x, y) { //形参接收的值：还是生成器函数执行的时候传递的值，和next执行传递的值没关系
  console.log(x, y)
  console.log('A')
  let n = yield 10
  console.log('B', n)
  let m = yield 20
  console.log('C', m)
}
let itor = fn(100, 200)
console.log(itor.next(1)) //输出‘100,200 / A’  返回{value: 10, done: false}
console.log(itor.next(2)) //输出‘B / 2’  返回{value: 20, done: false}
console.log(itor.next(3)) //输出‘C / 3’  返回{value: undefined, done: true} */